package com.bright.hxj.qchz.util;

import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NBExpressUtil {

    // 单表情况 逐行横向比较
    public static List<String> checkHorizontal(String ztId, int years, String tableDescription, String leftRuleExpress, String rightRuleExpress, String leftCond, String rightCond, String opt,
                                           String ruleDescription, List<Map<String, String>> tableDataList) {
        List<String> result = new ArrayList<>();

        int i = 1;
        boolean isNotNull = false;
        for (Map<String, String> tableDataMap : tableDataList) {
            // 左值
            BigDecimal s = analysisExpress(leftRuleExpress, leftCond, tableDataMap);
            // 右值
            BigDecimal s1 = analysisExpress(rightRuleExpress, rightCond, tableDataMap);

            // 根据操作符比较 返回校验信息
            if (s != null && s1 != null) {
                isNotNull = true;
                String errorMsg = "稽核单位 " + ztId + " " + tableDescription + " 第" + i + "行 " + ruleDescription + "不满足！左值：" + s + ", 右值：" + s1;
                if (!compareData(s, s1, opt)) {
                    result.add(errorMsg);
                }
            }
        }

        if (!isNotNull) {
//            result.add("稽核单位 " + ztId + " " + tableDescription + "当前规则取不到值，或不满足条件！" + ruleDescription);
            System.out.println("稽核单位 " + ztId + " " + tableDescription + " 当前规则取不到值，或不满足条件！" + ruleDescription);
        }

        return result;
    }

    // 跨表情况 每张表每个表达式取一个值
    public static List<String> checkBetweenTables(String ztId, int years, String tableDescription, String leftRuleExpress, String rightRuleExpress, String leftCond, String rightCond, String opt,
                                                  String ruleDescription, Map<String, List<Map<String, String>>> tableDataMap) {
        //
        List<String> result = new ArrayList<>();
        int i = 1;
        boolean isNotNull = false;
        BigDecimal s = analysisExpressBetweenTables(leftRuleExpress, leftCond, tableDataMap);
        // 右值
        BigDecimal s1 = analysisExpressBetweenTables(rightRuleExpress, rightCond, tableDataMap);

        // 根据操作符比较 返回校验信息
        if (s != null && s1 != null) {
            isNotNull = true;
            String errorMsg = "稽核单位 " + ztId + " " + tableDescription + " 第" + i + "行 " + ruleDescription + "不满足！左值：" + s + ", 右值：" + s1;
            if (!compareData(s, s1, opt)) {
                result.add(errorMsg);
            }
        }

        if (!isNotNull) {
//            result.add("稽核单位 " + ztId + " " + tableDescription + "当前规则取不到值，或不满足条件！" + ruleDescription);
            System.out.println("稽核单位 " + ztId + " " + tableDescription + " 当前规则取不到值，或不满足条件！" + ruleDescription);
        }

        return result;
    }

    // 单表 横向校验
//    private static BigDecimal analysisExpress(String express, String cond, Map<String, String> tableDataMap) {
//
////        StringBuffer sbf = new StringBuffer();
//
//        String otherExpress = express;
//        String otherCond = cond;
//        BigDecimal resultValue = BigDecimal.ZERO;
////        String sql = null;
////        String groupSql = "";
////        String sqlzbHeand = " select b.rid,b.zid,b.years," + ((tableOptType == 2 || tableOptType == 3) ? "b.months," : "") + "b.tabledec,b.shortdist, b.distid,b.distname,b.lx,b.lxname,b.detail,b.opt";
////        sqlzb += ")b";
////        try {
//
//            //BigDecimal zero = new BigDecimal("0.0");
//            String outerLastOption = "start", outerOption = ""; // 记录中括号之间的操作符
////            String tabStr = "";
////            String sqlon = "";
////            if (otherExpress.indexOf("[") == -1) value = otherExpress + "+0.1-0.1";
//
//            int i = 0;
//            // 这里每次解析一个中括号  [rep901|c1+c2]+[rep905|c3]
//            while (otherExpress.indexOf("[") != -1) {
//                i++;
////                tabStr = "r" + i;
//                String tmpExpress = otherExpress.substring(otherExpress.indexOf("[") + 1, otherExpress.indexOf("]"));
//                String tmpCond = StringUtils.isEmpty(otherCond) ? null : otherCond.substring(otherCond.indexOf("[") + 1, otherCond.indexOf("]"));
//                String expressTableName = tmpExpress.substring(0, tmpExpress.indexOf("|")), expressFieldName = tmpExpress.substring(tmpExpress.indexOf("|") + 1, tmpExpress.length());
//
//                //解析cond
//                String condFieldName = tmpCond == null ? null : tmpCond.substring(0, tmpCond.indexOf("|"));
//                String subCond = tmpCond == null ? null : tmpCond.substring(tmpCond.indexOf("|") + 1);
////                String condFieldValue = null, condOptChar = "=";
//                boolean isEquals = true, isThreeColumn = false;
//                if (subCond == null || subCond.indexOf("|") == -1) {
////                    condFieldValue = StringUtils.isNumeric(subCond) ? subCond : "'" + subCond + "'";
//                } else {
////                    condFieldValue = subCond.substring(0, subCond.indexOf("|"));
//                    String v = subCond.substring(subCond.indexOf("|") + 1);
//
//                    isThreeColumn = true;
//                    if (!StringUtils.equals(v, "1")) {
//                        isEquals = false;
////                        condOptChar = "<>";
//                    }
//
////                    condFieldValue = "'" + condFieldValue + "'";
//                }
//
//                System.out.println();
//                // 这里获得解析出来的内容
//                // expressTableName是表名
//                // expressFieldName是包含字段名的表达式 未经过进一步解析？
//                System.out.println(expressFieldName+ "   " + expressTableName);
//
//                // 解析出条件 e.g.: subCond=汇总数  condFieldName=lx  condOptChar=条件的操作符 等于或不等于  isEquals=true时是等于
//                System.out.println(subCond  + "   " + condFieldName + "  " + isEquals);
//
//
//                // 解析表达式 把符号拆出来 setValueList
//                List<String> valueList = setValueList(expressFieldName);
//
//                // 把值代进去 replace进表达式
//                String lastOption = "start", option = "";
//                BigDecimal partCalculateValue = BigDecimal.ZERO;
//                for (String eachFieldOfExpress : valueList) {
//                    BigDecimal value = BigDecimal.ZERO;
//                    if (!StringUtils.isNumeric(eachFieldOfExpress)) {
//
//                        if (StringUtils.endsWithAny(eachFieldOfExpress, "+", "-", "*", "/")) {
//                            // 获取操作符
//                            option = eachFieldOfExpress.substring(eachFieldOfExpress.length() - 1);
//                            // 把末尾的操作符去掉
//                            eachFieldOfExpress = StringUtils.substring(eachFieldOfExpress, 0, eachFieldOfExpress.length() - 1);
//                        }
//                        value = getValueByFieldWithCond(tableDataMap, otherCond, condFieldName, subCond, isEquals, eachFieldOfExpress, value);
//                    } else {
//                        // 表达式就是数值
//                        value = BigDecimal.valueOf(Double.parseDouble(eachFieldOfExpress));
//                    }
//
//                    // 根据操作符进行计算
//                    partCalculateValue = calculateByOpt(lastOption, partCalculateValue, value);
//                    //System.out.println("当前子公式的值："+oneValue);
//                    //System.out.println("相加后的值："+tempValue);
//                    lastOption = option;
//                }
////                String expressAfterReplace = "";
//
//                // 计算 CalculationUtils
////                Double calculation = CalculationUtils.calculation(expressAfterReplace);
////                value += calculation;
//
//                // 有多个中括号时 还要识别中括号之间的操作符
//                outerOption = otherExpress.substring(0, otherExpress.indexOf("["));
//                resultValue = calculateByOpt(outerLastOption, resultValue, partCalculateValue);
//                //System.out.println("当前子公式的值："+oneValue);
//                //System.out.println("相加后的值："+tempValue);
//                outerLastOption = outerOption;
//
//
//                otherExpress = otherExpress.substring(otherExpress.indexOf("]") + 1);
//                otherCond = StringUtils.isNotEmpty(otherCond) ? otherCond.substring(otherCond.indexOf("]") + 1) : null;
//            }
////            if (null == symbol || StringUtils.isEmpty(symbol)) symbol = "0";
////            sqlzbHeand += ",${isnull}(" + symbol + ",0) bb from (" + sqlzb;
////
////        } catch (Exception e) {
////            logger.error("error:", e);
////        }
//
//        return resultValue;
//
//    }

    // 修改 按四则运算法则的顺序运算
    private static BigDecimal analysisExpress(String express, String cond, Map<String, String> tableDataMap) {

        String otherExpress = express;
        String otherCond = cond;
//        BigDecimal resultValue = BigDecimal.ZERO;

        String outerLastOption = "start", outerOption = ""; // 记录中括号之间的操作符

        String outerExpressAfterReplace = otherExpress; // 外层 所有中括号被替换为具体值后的表达式

//        int i = 0;
        // 这里每次解析一个中括号  [rep901|c1+c2]+[rep905|c3]
        while (otherExpress.indexOf("[") != -1) {
//            i++;
//            String tmpExpress = otherExpress.substring(otherExpress.indexOf("[") + 1, otherExpress.indexOf("]"));
//            String tmpCond = StringUtils.isEmpty(otherCond) ? null : otherCond.substring(otherCond.indexOf("[") + 1, otherCond.indexOf("]"));
////            String expressTableName = tmpExpress.substring(0, tmpExpress.indexOf("|")),
//            String expressFieldName = tmpExpress.substring(tmpExpress.indexOf("|") + 1, tmpExpress.length());
//
//            //解析cond
//            String condFieldName = tmpCond == null ? null : tmpCond.substring(0, tmpCond.indexOf("|"));
//            String subCond = tmpCond == null ? null : tmpCond.substring(tmpCond.indexOf("|") + 1);
//            boolean isEquals = true;
//            if (subCond == null || subCond.indexOf("|") == -1) {
////                    condFieldValue = StringUtils.isNumeric(subCond) ? subCond : "'" + subCond + "'";
//            } else {
////                    condFieldValue = subCond.substring(0, subCond.indexOf("|"));
//                String v = subCond.substring(subCond.indexOf("|") + 1);
//                if (!StringUtils.equals(v, "1")) {
//                    isEquals = false;
//                }
//            }

            // 获得解析出来的内容
            // expressTableName是表名
            // expressFieldName是包含字段名的表达式 未经过进一步解析？
            // 解析出条件 e.g.: subCond=汇总数  condFieldName=lx  condOptChar=条件的操作符 等于或不等于  isEquals=true时是等于
            String[] components = getExpressComponent(otherExpress, otherCond);
            String expressTableName = components[0], expressFieldName = components[1], condFieldName = components[2], subCond = components[3];
            boolean isEquals = Boolean.parseBoolean(components[4]);

            // 解析表达式 把符号拆出来 c1+c2+c3 -> [c1+, c2+, c3]
            List<String> valueList = getSeperatedFieldsWithOpt(expressFieldName);


            String lastOption = "start", option = "";
            String expressAfterReplace = expressFieldName;

            for (String eachFieldOfExpress : valueList) {
                BigDecimal value;
                if (StringUtils.endsWithAny(eachFieldOfExpress, "+", "-", "*", "/")) {
                    // 获取操作符
                    option = eachFieldOfExpress.substring(eachFieldOfExpress.length() - 1);
                    // 把末尾的操作符去掉
                    eachFieldOfExpress = StringUtils.substring(eachFieldOfExpress, 0, eachFieldOfExpress.length() - 1);
                } else {
                    option = "";
                }
                if (!NumberUtils.isNumber(eachFieldOfExpress)) {
                    value = getValueByFieldWithCond(tableDataMap, otherCond, condFieldName, subCond, isEquals, eachFieldOfExpress);
                    expressAfterReplace = replaceCalculationIntoExpress(value, expressAfterReplace, eachFieldOfExpress, option);
                } else {
                    // 表达式就是数值 不用替换
//                    value = BigDecimal.valueOf(Double.parseDouble(eachFieldOfExpress));
                }

                // 根据操作符进行计算
//                partCalculateValue = calculateByOpt(lastOption, partCalculateValue, value);
//                lastOption = option;

            }

            System.out.println("内层替换完的表达式：" + expressAfterReplace);
            // 计算 CalculationUtils
            BigDecimal calculation = calculateExpress(expressAfterReplace);

            // 有多个中括号时 还要识别中括号之间的操作符
            outerOption = otherExpress.substring(0, otherExpress.indexOf("["));
//            resultValue = calculateByOpt(outerLastOption, resultValue, partCalculateValue);
//            outerLastOption = outerOption;

            // 替换外层表达式
//            String replaceValue = calculation == null ? "" : calculation + outerOption;
//            outerExpressAfterReplace = StringUtils.replace(outerExpressAfterReplace, otherExpress + outerOption, replaceValue);
            outerExpressAfterReplace = replaceCalculationIntoExpress(calculation, outerExpressAfterReplace, otherExpress, outerOption);

            otherExpress = otherExpress.substring(otherExpress.indexOf("]") + 1);
            otherCond = StringUtils.isNotEmpty(otherCond) ? otherCond.substring(otherCond.indexOf("]") + 1) : null;
        }

//        System.out.println("外层替换完的表达式：" + outerExpressAfterReplace);

        return calculateExpress(outerExpressAfterReplace);

    }

    private static String[] getExpressComponent(String otherExpress, String otherCond) {
        // 分析获取表达式的各个要素 表名 字段表达式 条件字段 条件值 条件操作符是否为相等
//        String[] result = new String[5];

        String tmpExpress = otherExpress.substring(otherExpress.indexOf("[") + 1, otherExpress.indexOf("]"));
        String tmpCond = StringUtils.isEmpty(otherCond) ? null : otherCond.substring(otherCond.indexOf("[") + 1, otherCond.indexOf("]"));
        String expressTableName = tmpExpress.substring(0, tmpExpress.indexOf("|"));
        String expressFieldName = tmpExpress.substring(tmpExpress.indexOf("|") + 1, tmpExpress.length());

        //解析cond
        String condFieldName = tmpCond == null ? null : tmpCond.substring(0, tmpCond.indexOf("|"));
        String subCond = tmpCond == null ? null : tmpCond.substring(tmpCond.indexOf("|") + 1);
        boolean isEquals = true;
        if (subCond == null || subCond.indexOf("|") == -1) {
//                    condFieldValue = StringUtils.isNumeric(subCond) ? subCond : "'" + subCond + "'";
        } else {
//                    condFieldValue = subCond.substring(0, subCond.indexOf("|"));
            String v = subCond.substring(subCond.indexOf("|") + 1);
            if (!StringUtils.equals(v, "1")) {
                isEquals = false;
            }
        }

//        result[0] = expressTableName; // 表名
//        result[1] = expressFieldName; // 字段表达式
//        result[2] = condFieldName; // 条件字段名
//        result[3] = subCond; // 条件值
//        result[4] = String.valueOf(isEquals); // 条件操作符是否为相等
        return new String[] {expressTableName, expressFieldName, condFieldName, subCond, String.valueOf(isEquals)};
    }

    private static BigDecimal calculateExpress(String expressAfterReplace) {
        BigDecimal calculation;
        if (StringUtils.isEmpty(expressAfterReplace)) {
            calculation = null;
        } else {
            calculation = CalculationUtils.calculation(expressAfterReplace);
        }
        return calculation;
    }

    private static String replaceCalculationIntoExpress(Number calculation, String express, String replaceField, String option) {
        // 取不到值 或条件不符 value会为空
        String replaceValue = calculation == null ? "" : calculation + option;
        // 把值代进去 replace进表达式；value为空的情况 替换为空字符串
        express = StringUtils.replace(express, replaceField + option, replaceValue);
        return express;
    }

    private static BigDecimal getValueByFieldWithCond(Map<String, String> tableDataMap, String otherCond, String condFieldName, String subCond, boolean isEquals, String eachFieldOfExpress) {
        // 获取该字段的值

        BigDecimal value = null;

        String expressFieldValueStr = tableDataMap.get(eachFieldOfExpress);
        if (expressFieldValueStr != null) {
            BigDecimal expressFieldValue = BigDecimal.valueOf(Double.parseDouble(expressFieldValueStr));


            // 判断cond 看条件是否满足
            if (StringUtils.isNotEmpty(otherCond)) {


                String condFieldValue = tableDataMap.get(condFieldName);
                if (isEquals) {
                    if (!StringUtils.equalsIgnoreCase(subCond, condFieldValue)) {
//                                    value = 0;
                    } else {
                        // 条件符合 取表达式所属值
                        value = expressFieldValue;
                    }
                } else {
                    // 条件是不等于的情况
                    if (StringUtils.equalsIgnoreCase(subCond, condFieldValue)) {
//                                    value = 0;
                    } else {
                        // 条件符合 取值
                        value = expressFieldValue;
                    }
                }

            } else {
                // 没有条件的情况
                value = BigDecimal.valueOf(Double.parseDouble(tableDataMap.get(eachFieldOfExpress)));
            }
        } else {
//                            throw new RuntimeException("取不到值！")
            System.out.println("异常：取不到值！" + eachFieldOfExpress + ", " + tableDataMap);
        }
        return value;
    }

    // 校验跨表的情况
//    private static BigDecimal analysisExpressBetweenTables(String express, String cond, Map<String, List<Map<String, String>>> tableDataMap) {
//
//        String otherExpress = express;
//        String otherCond = cond;
//        BigDecimal resultValue = BigDecimal.ZERO;
////        try {
//            String outerLastOption = "start", outerOption = ""; // 记录中括号之间的操作符
//
//            int i = 0;
//            // 这里每次解析一个中括号  [rep901|c1+c2]+[rep905|c3]
//            while (otherExpress.indexOf("[") != -1) {
//                i++;
////                tabStr = "r" + i;
//                String tmpExpress = otherExpress.substring(otherExpress.indexOf("[") + 1, otherExpress.indexOf("]"));
//                String tmpCond = StringUtils.isEmpty(otherCond) ? null : otherCond.substring(otherCond.indexOf("[") + 1, otherCond.indexOf("]"));
//                String expressTableName = tmpExpress.substring(0, tmpExpress.indexOf("|")), expressFieldName = tmpExpress.substring(tmpExpress.indexOf("|") + 1, tmpExpress.length());
//
//                //解析cond
//                String condFieldName = tmpCond == null ? null : tmpCond.substring(0, tmpCond.indexOf("|"));
//                String subCond = tmpCond == null ? null : tmpCond.substring(tmpCond.indexOf("|") + 1);
//                boolean isEquals = true, isThreeColumn = false;
//                if (subCond == null || subCond.indexOf("|") == -1) {
////                    condFieldValue = StringUtils.isNumeric(subCond) ? subCond : "'" + subCond + "'";
//                } else {
////                    condFieldValue = subCond.substring(0, subCond.indexOf("|"));
//                    String v = subCond.substring(subCond.indexOf("|") + 1);
//
//                    isThreeColumn = true;
//                    if (!StringUtils.equals(v, "1")) {
//                        isEquals = false;
////                        condOptChar = "<>";
//                    }
////                    condFieldValue = "'" + condFieldValue + "'";
//                }
//
//                // 这里获得解析出来的内容
//                // expressTableName是表名
//                // expressFieldName是包含字段名的表达式 未经过进一步解析？
//                System.out.println(expressFieldName+ "   " + expressTableName);
//
//                // 解析出条件 e.g.: subCond=汇总数  condFieldName=lx  condOptChar=条件的操作符 等于或不等于  isEquals=true时是等于
//                System.out.println(subCond  + "   " + condFieldName + "  " + isEquals);
//
//
//                // 解析表达式 把符号拆出来 c1+c2+c3 -> [c1+, c2+, c3]
//                List<String> valueList = setValueList(expressFieldName);
//
//                // 把值代进去 replace进表达式
//                String lastOption = "start", option = "";
//                BigDecimal partCalculateValue = BigDecimal.ZERO;
//                for (String eachFieldOfExpress : valueList) {
//                    BigDecimal value = BigDecimal.ZERO;
//                    if (!StringUtils.isNumeric(eachFieldOfExpress)) {
//
//                        if (StringUtils.endsWithAny(eachFieldOfExpress, "+", "-", "*", "/")) {
//                            // 获取操作符
//                            option = eachFieldOfExpress.substring(eachFieldOfExpress.length() - 1);
//                            // 把末尾的操作符去掉 如“c1+” -》 “c1”
//                            eachFieldOfExpress = StringUtils.substring(eachFieldOfExpress, 0, eachFieldOfExpress.length() - 1);
//                        }
//
//                        List<Map<String, String>> maps = tableDataMap.get(expressTableName);
//                        if (maps.size() == 1) {
//                            // 只有一行 直接取
//                            Map<String, String> map = maps.get(0);
//                            value = getValueByFieldWithCond(map, cond, condFieldName, subCond, isEquals, eachFieldOfExpress, value);
//                        } else {
//                            // 不止一行
//                            if (StringUtils.isNotEmpty(otherCond)) {
//                                // 判断cond 看条件是否满足
//                                for (Map<String, String> map : maps) {
//                                    value = getValueByFieldWithCond(map, otherCond, condFieldName, subCond, isEquals, eachFieldOfExpress, value);
//                                    if (value.compareTo(BigDecimal.ZERO) != 0) {
//                                        break;
//                                    }
//                                }
//                            } else {
//                                throw new RuntimeException("不止一条数据，请检查是数据问题还是规则配置错误！（规则配置cond条件）");
//                            }
//                        }
//                    } else {
//                        // 表达式就是数值
//                        value = BigDecimal.valueOf(Double.parseDouble(eachFieldOfExpress));
//                    }
//
//                    // 根据操作符进行计算
//                    partCalculateValue = calculateByOpt(lastOption, partCalculateValue, value);
//                    //System.out.println("当前子公式的值："+oneValue);
//                    //System.out.println("相加后的值："+tempValue);
//                    lastOption = option;
//                }
////                String expressAfterReplace = "";
//
//                // 计算 CalculationUtils
////                Double calculation = CalculationUtils.calculation(expressAfterReplace);
////                value += calculation;
//
//                // 有多个中括号时 还要识别中括号之间的操作符
//                outerOption = otherExpress.substring(0, otherExpress.indexOf("["));
//                resultValue = calculateByOpt(outerLastOption, resultValue, partCalculateValue);
//                //System.out.println("当前子公式的值："+oneValue);
//                //System.out.println("相加后的值："+tempValue);
//                outerLastOption = outerOption;
//
//
//                otherExpress = otherExpress.substring(otherExpress.indexOf("]") + 1);
//                otherCond = StringUtils.isNotEmpty(otherCond) ? otherCond.substring(otherCond.indexOf("]") + 1) : null;
//            }
////            if (null == symbol || StringUtils.isEmpty(symbol)) symbol = "0";
////            sqlzbHeand += ",${isnull}(" + symbol + ",0) bb from (" + sqlzb;
////
////        } catch (Exception e) {
////            logger.error("error:", e);
////        }
//
//        return resultValue;
//
//    }

    private static BigDecimal analysisExpressBetweenTables(String express, String cond, Map<String, List<Map<String, String>>> tableDataMap) {

        String otherExpress = express;
        String otherCond = cond;
        BigDecimal resultValue = BigDecimal.ZERO;
//        try {
        String outerLastOption = "start", outerOption = ""; // 记录中括号之间的操作符
        String outerExpressAfterReplace = otherExpress; // 外层 替换中括号为具体值后的表达式

        // 这里每次解析一对中括号内的表达式  [rep901|c1+c2]+[rep905|c3]
        while (otherExpress.indexOf("[") != -1) {
//            String tmpExpress = otherExpress.substring(otherExpress.indexOf("[") + 1, otherExpress.indexOf("]"));
//            String tmpCond = StringUtils.isEmpty(otherCond) ? null : otherCond.substring(otherCond.indexOf("[") + 1, otherCond.indexOf("]"));
//            String expressTableName = tmpExpress.substring(0, tmpExpress.indexOf("|")), expressFieldName = tmpExpress.substring(tmpExpress.indexOf("|") + 1, tmpExpress.length());
//
//            //解析cond
//            String condFieldName = tmpCond == null ? null : tmpCond.substring(0, tmpCond.indexOf("|"));
//            String subCond = tmpCond == null ? null : tmpCond.substring(tmpCond.indexOf("|") + 1);
//            boolean isEquals = true, isThreeColumn = false;
//            if (subCond == null || subCond.indexOf("|") == -1) {
////                    condFieldValue = StringUtils.isNumeric(subCond) ? subCond : "'" + subCond + "'";
//            } else {
////                    condFieldValue = subCond.substring(0, subCond.indexOf("|"));
//                String v = subCond.substring(subCond.indexOf("|") + 1);
//
//                if (!StringUtils.equals(v, "1")) {
//                    isEquals = false;
//                }
////                    condFieldValue = "'" + condFieldValue + "'";
//            }

            // 这里获得解析出来的内容
            // expressTableName是表名
            // expressFieldName是包含字段名的表达式 未经过进一步解析？
            // 解析出条件 e.g.: subCond=汇总数  condFieldName=lx  condOptChar=条件的操作符 等于或不等于  isEquals=true时是等于
            String[] components = getExpressComponent(otherExpress, otherCond);
            String expressTableName = components[0], expressFieldName = components[1], condFieldName = components[2], subCond = components[3];
            boolean isEquals = Boolean.parseBoolean(components[4]);

            // 解析表达式 把符号拆出来 c1+c2+c3 -> [c1+, c2+, c3]
            List<String> valueList = getSeperatedFieldsWithOpt(expressFieldName);

            String lastOption = "start", option = "";
            String expressAfterReplace = expressFieldName;
            for (String eachFieldOfExpress : valueList) {
                BigDecimal value;

                if (StringUtils.endsWithAny(eachFieldOfExpress, "+", "-", "*", "/")) {
                    // 获取操作符
                    option = eachFieldOfExpress.substring(eachFieldOfExpress.length() - 1);
                    // 把末尾的操作符去掉 如“c1+” -》 “c1”
                    eachFieldOfExpress = StringUtils.substring(eachFieldOfExpress, 0, eachFieldOfExpress.length() - 1);
                } else {
                    option = "";
                }


                if (!NumberUtils.isNumber(eachFieldOfExpress)) {

                    List<Map<String, String>> maps = tableDataMap.get(expressTableName);
                    if (maps.size() == 1) {
                        // 只有一行 直接取
                        Map<String, String> map = maps.get(0);
                        value = getValueByFieldWithCond(map, cond, condFieldName, subCond, isEquals, eachFieldOfExpress);
                        // 把值代进去 replace进表达式
//                        expressAfterReplace = StringUtils.replace(expressAfterReplace, eachFieldOfExpress + option, value + option);
                        expressAfterReplace = replaceCalculationIntoExpress(value, expressAfterReplace, eachFieldOfExpress, option);
                    } else {
                        // 不止一行
                        if (StringUtils.isNotEmpty(otherCond)) {
                            // 判断cond 看条件是否满足
                            for (Map<String, String> map : maps) {
                                value = getValueByFieldWithCond(map, otherCond, condFieldName, subCond, isEquals, eachFieldOfExpress);
                                // 把值代进去 replace进表达式
//                                expressAfterReplace = StringUtils.replace(expressAfterReplace, eachFieldOfExpress + option, value + option);
                                expressAfterReplace = replaceCalculationIntoExpress(value, expressAfterReplace, eachFieldOfExpress, option);
                                if (value.compareTo(BigDecimal.ZERO) != 0) {
                                    break;
                                }
                            }
                        } else {
                            throw new RuntimeException("不止一条数据，请检查是数据问题还是规则配置错误！（规则配置cond条件）");
                        }
                    }
                } else {
                    // 表达式就是数值
//                    value = BigDecimal.valueOf(Double.parseDouble(eachFieldOfExpress));
                }

            }
            System.out.println("内层替换完的表达式：" + expressAfterReplace);
            // 计算 CalculationUtils
//            Double calculation = CalculationUtils.calculation(expressAfterReplace);
            BigDecimal calculation = calculateExpress(expressAfterReplace);

            // TODO 有多个中括号时 还要识别中括号之间的操作符
            outerOption = otherExpress.substring(0, otherExpress.indexOf("["));
            // 替换外层表达式
//            outerExpressAfterReplace = StringUtils.replace(outerExpressAfterReplace, otherExpress + outerOption, calculation + outerOption);
            outerExpressAfterReplace = replaceCalculationIntoExpress(calculation, outerExpressAfterReplace, otherExpress, outerOption);

            otherExpress = otherExpress.substring(otherExpress.indexOf("]") + 1);
            otherCond = StringUtils.isNotEmpty(otherCond) ? otherCond.substring(otherCond.indexOf("]") + 1) : null;
        }

        System.out.println("外层替换完的表达式：" + outerExpressAfterReplace);
//        Double calculation = CalculationUtils.calculation(outerExpressAfterReplace);

        return calculateExpress(outerExpressAfterReplace);

    }

    private static BigDecimal calculateByOpt(String lastOption, BigDecimal partCalculateValue, BigDecimal value) {
        if (lastOption.equalsIgnoreCase("start")) {
            partCalculateValue = value;
        } else if (lastOption.equalsIgnoreCase("+")) {
            partCalculateValue = partCalculateValue.add(value);

        } else if (lastOption.equalsIgnoreCase("-")) {
            partCalculateValue = partCalculateValue.subtract(value);

        } else if (lastOption.equalsIgnoreCase("*")) {
            partCalculateValue = partCalculateValue.multiply(value);

        } else if (lastOption.equalsIgnoreCase("/")) {
            partCalculateValue = partCalculateValue.divide(value, 2, RoundingMode.HALF_UP);
        }
        return partCalculateValue;
    }

    // 跨表的情况 获取需要用到哪些表的数据
    public static String[] getOtherTableTypeNames(String leftRule, String rightRule) {
        // TODO
        Set<String> result = new HashSet<>();

        String[] rules = new String[] {leftRule, rightRule};
        for (String rule : rules) {
            String express = rule;
            while (express.indexOf("[") != -1) {
//                i++;
                String tmpExpress = express.substring(express.indexOf("[") + 1, express.indexOf("]"));
                String expressTableName = tmpExpress.substring(0, tmpExpress.indexOf("|"));
                result.add(expressTableName);

                express = express.substring(express.indexOf("]") + 1);
            }
        }

        return result.toArray(new String[0]);
    }

    private static boolean compareData(BigDecimal value1, BigDecimal value2, String opt) {

        if (value1.compareTo(BigDecimal.ZERO) == 0 && value2.compareTo(BigDecimal.ZERO) == 0) {
            return true;
        }
        if (StringUtils.equals(opt, "=")) {
            return value1.compareTo(value2) == 0;
        }
        if (StringUtils.equals(opt, ">")) {
            return value1.compareTo(value2) > 0;
        }
        if (StringUtils.equals(opt, ">=")) {
            return value1.compareTo(value2) >= 0;
        }
        if (StringUtils.equals(opt, "<")) {
            return value1.compareTo(value2) < 0;
        }
        if (StringUtils.equals(opt, "<=")) {
            return value1.compareTo(value2) <= 0;
        }
        if (StringUtils.equals(opt, "<>")) {
            return value1.compareTo(value2) != 0;
        }
        return false;
    }

    private static List<String> getSeperatedFieldsWithOpt(String rightValueStr) {
//        List<List<String>> valueList = new ArrayList<List<String>>();
//        List<String> leftValueList = new ArrayList<String>();
        List<String> rightValueList = new ArrayList<String>();
        String regexStr = "([^\\-|^\\+|^\\*|^/]+)(\\-|\\+|\\*|/)";
        Pattern p = Pattern.compile(regexStr);
        Matcher m = p.matcher(rightValueStr);
        while (m.find()) {
            rightValueList.add(m.group());
        }
        if (rightValueList.size() == 0) {
            rightValueList.add(rightValueStr);
        } else {
            String lastStr = rightValueList.get(rightValueList.size() - 1);
            String opt = "\\" + lastStr.substring(lastStr.length() - 1);
            String[] temp = rightValueStr.split(opt);
            rightValueList.add(temp[temp.length - 1]);
        }
        return rightValueList;
    }

}
